package io.github.wppli.trigger.http;

import cc.jq1024.middleware.token.service.ITokenService;
import com.alibaba.fastjson.JSON;
import io.github.wppli.domain.authenticate.model.entity.UserEntity;
import io.github.wppli.domain.authenticate.service.IAccountService;
import io.github.wppli.domain.authenticate.model.entity.SingInEntity;
import io.github.wppli.domain.authenticate.model.entity.SingInUserInfoEntity;
import io.github.wppli.domain.authenticate.service.IAuthenticateService;
import io.github.wppli.domain.authenticate.service.engine.factory.AuthenticateFactory;
import io.github.wppli.trigger.api.IUserAuthenticateService;
import io.github.wppli.trigger.api.dto.user_authenticate.*;
import io.github.wppli.types.common.Validator;
import io.github.wppli.types.enums.ResponseCode;
import io.github.wppli.types.exception.AppException;
import io.github.wppli.types.exception.CacheCodeIllegalException;
import io.github.wppli.types.model.Response;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;


import static io.github.wppli.types.common.Constant.LOGIN_CODE;
import static io.github.wppli.types.enums.ResponseCode.CACHE_CODE_ILLEGAL;


/**
 * 用户认证
 * @author li--jiaqiang 2024−12−23
 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/user/authenticate/")
@CrossOrigin(value = {"${app.config.cross-origin:http://116.198.239.101:3000/}", "http://localhost:3000/"})
public class UserAuthenticateController implements IUserAuthenticateService {

    private final IAuthenticateService authenticateService;
    private final IAccountService accountService;
    private final ITokenService tokenService;

    /**
     * 快捷登录
     * @param signInRequest 登录请求实体
     */
    @Override
    @RequestMapping(value = "login", method = RequestMethod.POST)
    public Response<SingInResponse> signIn(@RequestBody SignInRequest signInRequest) {
        try {
            log.info("UserAuthenticateController.signIn(). 登录开始执行...");
            // 1. 参数校验
            if (StringUtils.isAnyBlank(signInRequest.getPasswordCode(), signInRequest.getContactInformation())) {
                log.warn("UserAuthenticateController.signIn(). 参数错误: {}", JSON.toJSONString(signInRequest));
                return Response.<SingInResponse>builder()
                        .code(ResponseCode.ILLEGAL_PARAMETER.getCode())
                        .info(ResponseCode.ILLEGAL_PARAMETER.getInfo())
                        .build();
            }
            // 2. 业务
            SingInEntity singInEntity = SingInEntity.builder()
                    .contactInformation(signInRequest.getContactInformation())
                    .passwordCode(signInRequest.getPasswordCode())
                    .code(AuthenticateFactory.getEngineType(signInRequest.getCode()))
                    .build();
            SingInUserInfoEntity singInUserInfoEntity = authenticateService.signIn(singInEntity);
            // 3. 参数转换
            UserEntity userEntity = singInUserInfoEntity.getUserEntity();
            SingInResponse singInResponse = SingInResponse.builder()
                    .token(singInUserInfoEntity.getToken())
                    .bio(userEntity.getBio())
                    .avatarUrl(userEntity.getAvatarUrl())
                    .age(userEntity.getAge())
                    .username(userEntity.getUsername())
                    .followCount(userEntity.getFollowCount())
                    .favoriteCount(userEntity.getFavoriteCount())
                    .followerCount(userEntity.getFollowerCount())
                    .build();
            // 4. 返回结果
            log.info("UserAuthenticateController.signIn(). 执行完毕");
            return Response.<SingInResponse>builder()
                    .data(singInResponse)
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo())
                    .build();
        } catch (AppException exception) {
            log.error("AppException: ",exception);
            return Response.<SingInResponse>builder()
                    .code(exception.getCode())
                    .info(exception.getInfo())
                    .build();
        } catch (Exception exception) {
            log.error("Exception: ",exception);
            return Response.<SingInResponse>builder()
                    .code(ResponseCode.SERVER_ERROR.getCode())
                    .info(ResponseCode.SERVER_ERROR.getInfo())
                    .build();
        }
    }

    /**
     *
     * @param registerRequest
     * .contactInformation 联系方式: 电话 or 邮箱
     * .code 验证码
     */
    @Override
    @RequestMapping(value = "register", method = RequestMethod.POST)
    public Response<RegisterResponse> register(@RequestBody RegisterRequest registerRequest) {
        try {
            log.debug("UserAuthenticateController.register 开始注册: {}", registerRequest.toString());
            // 参数校验
            if (StringUtils.isAnyBlank(registerRequest.getContactInformation(), registerRequest.getCode())) {
                throw new IllegalArgumentException();
            }
            // 业务
            // 0. 校验验证码
            boolean verified = authenticateService.verifyCode(registerRequest.getContactInformation(), registerRequest.getCode());
            if (!verified) {
                // 验证码错误
                throw new CacheCodeIllegalException(CACHE_CODE_ILLEGAL.getCode(), CACHE_CODE_ILLEGAL.getInfo());
            }
            // 1. 校验账号是否注册
            accountService.verifyAccountExist(registerRequest.getContactInformation());
            // 2. 进行注册
            accountService.register(registerRequest.getContactInformation(), registerRequest.getType());
            // 返回结果
            return Response.<RegisterResponse>builder()
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo())
                    .build();
        } catch (IllegalArgumentException exception) {
            log.error("UserAuthenticateController.register: {}", "参数异常");
            return Response.<RegisterResponse>builder()
                    .code(ResponseCode.ILLEGAL_PARAMETER.getCode())
                    .info(exception.getMessage() == null ? ResponseCode.ILLEGAL_PARAMETER.getCode() : exception.getMessage())
                    .build();
        } catch (AppException exception) {
            log.error("UserAuthenticateController.register - AppException: {}", exception.getInfo());
            return Response.<RegisterResponse>builder()
                    .code(exception.getCode())
                    .info(exception.getInfo())
                    .build();
        } catch (Exception exception) {
            log.error("UserAuthenticateController.register - Exception: {}", exception.getMessage());
            return Response.<RegisterResponse>builder()
                    .code(ResponseCode.SERVER_ERROR.getCode())
                    .info(ResponseCode.SERVER_ERROR.getInfo())
                    .build();
        }
    }

    /**
     * <a href="http://localhost:8089/api/v1/user/authenticate/code?contactInformation=2148660566@qq.com&type=2">...</a>
     * <a href="http://localhost:8089/api/v1/user/authenticate/code?contactInformation=18722864552&type=1">...</a>
     * @param contactInformation 联系方式 电话 or 邮箱
     * @param type 类型 1:电话， 2:邮箱
     */
    @Override
    @RequestMapping(value = "code", method = RequestMethod.GET)
    public Response<String> genCode(@RequestParam String contactInformation, @RequestParam Integer type) {
        try {
            log.info("UserAuthenticateController.genCode() 开始准备发送验证码");
            if (StringUtils.isAnyBlank(contactInformation)) {
                return Response.<String>builder()
                        .code(ResponseCode.ILLEGAL_PARAMETER.getCode())
                        .info(ResponseCode.ILLEGAL_PARAMETER.getInfo())
                        .build();
            }
            // 生成验证码
            String code = authenticateService.genCode(contactInformation, LOGIN_CODE);
            // 发送验证码
            authenticateService.sendCode(contactInformation, type, code);
            return Response.<String>builder()
                    .data(code)
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo())
                    .build();
        } catch (IllegalArgumentException exception) {
            log.error("UserAuthenticateController.genCode: {}", "参数异常");
            return Response.<String>builder()
                    .code(ResponseCode.ILLEGAL_PARAMETER.getCode())
                    .info(exception.getMessage() == null ? ResponseCode.ILLEGAL_PARAMETER.getCode() : exception.getMessage())
                    .build();
        } catch (AppException exception) {
            log.error("UserAuthenticateController.genCode - AppException: {}", exception.getInfo());
            return Response.<String>builder()
                    .code(exception.getCode())
                    .info(exception.getInfo())
                    .build();
        } catch (Exception exception) {
            log.error("UserAuthenticateController.genCode - Exception: {}", exception.getMessage());
            return Response.<String>builder()
                    .code(ResponseCode.SERVER_ERROR.getCode())
                    .info(ResponseCode.SERVER_ERROR.getInfo())
                    .build();
        }
    }

    /**
     * 设置密码接口 - 邮箱验证 or 短信验证
     */
    @Override
    @RequestMapping(value = "set-pas", method = RequestMethod.POST)
    public Response<String> setPassword(@RequestBody SetPasswordRequest setPasswordRequest) {

        try {
            log.info("UserAuthenticateController.setPassword - start: {}", "设置密码接口开始...");

            // 0. 参数验证
            if (StringUtils.isAnyBlank(setPasswordRequest.getPassword(), setPasswordRequest.getRepeatPassword(),
                    setPasswordRequest.getContactInformation())) {
                return Response.<String>builder()
                        .code(ResponseCode.ILLEGAL_PARAMETER.getCode())
                        .info(ResponseCode.ILLEGAL_PARAMETER.getInfo())
                        .build();
            }
            // 0. 校验密码格式
            if (!Validator.validatePassword(setPasswordRequest.getPassword())) {
                return Response.<String>builder()
                        .data("密码在6-18位之间，且不能包含空格和特殊字符，至少包含数字和字字母两种。")
                        .code(ResponseCode.RE_PASSWORD_FORMAT_ERROR.getCode())
                        .info(ResponseCode.RE_PASSWORD_FORMAT_ERROR.getInfo())
                        .build();
            }
            // 1. 校验两次密码是否相同
            if (!setPasswordRequest.getPassword().equals(setPasswordRequest.getRepeatPassword())) {
                return Response.<String>builder()
                        .code(ResponseCode.RE_PASSWORD_NOT_EQUAL.getCode())
                        .info(ResponseCode.RE_PASSWORD_NOT_EQUAL.getInfo())
                        .build();
            }
            // 2. 校验验证码
            if (!this.authenticateService.verifyCode(setPasswordRequest.getContactInformation(), setPasswordRequest.getCode())) {
                throw new CacheCodeIllegalException(CACHE_CODE_ILLEGAL.getCode(), CACHE_CODE_ILLEGAL.getInfo());
            }
            // 3. 设置密码
            this.accountService.setPassword(setPasswordRequest.getContactInformation(), setPasswordRequest.getPassword());
            return Response.<String>builder()
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo())
                    .build();
        } catch (IllegalArgumentException exception) {
            log.error("UserAuthenticateController.setPassword: {}", "参数异常");
            return Response.<String>builder()
                    .code(ResponseCode.ILLEGAL_PARAMETER.getCode())
                    .info(exception.getMessage() == null ? ResponseCode.ILLEGAL_PARAMETER.getCode() : exception.getMessage())
                    .build();
        } catch (AppException exception) {
            log.error("UserAuthenticateController.setPassword - AppException: {}", exception.getInfo());
            return Response.<String>builder()
                    .code(exception.getCode())
                    .info(exception.getInfo())
                    .build();
        } catch (Exception exception) {
            log.error("UserAuthenticateController.setPassword - Exception: {}", exception.getMessage());
            return Response.<String>builder()
                    .code(ResponseCode.SERVER_ERROR.getCode())
                    .info(ResponseCode.SERVER_ERROR.getInfo())
                    .build();
        } finally {
            log.info("UserAuthenticateController.setPassword - end: {}", "设置密码结束");
        }
    }

    /**
     * 绑定邮箱接口 - 邮箱验证
     */
    @Override
    @PostMapping("/bindEmail")
    public Response<String> bindEmail(@RequestBody BindEmailRequest bindEmailRequest, @RequestHeader("Authorization") String authorization) {
        try {
            log.info("UserAuthenticateController.bindEmail - start: {}", "设置密码接口开始...");
            // 0. 校验参数
            if (StringUtils.isAnyBlank(bindEmailRequest.getEmail(), bindEmailRequest.getCode())) {
                return Response.<String>builder()
                        .code(ResponseCode.ILLEGAL_PARAMETER.getCode())
                        .info(ResponseCode.ILLEGAL_PARAMETER.getInfo())
                        .build();
            }
            // 1. 校验验证码
            if (!this.authenticateService.verifyCode(bindEmailRequest.getEmail(), bindEmailRequest.getCode())) {
                throw new CacheCodeIllegalException(CACHE_CODE_ILLEGAL.getCode(), CACHE_CODE_ILLEGAL.getInfo());
            }
            // 2. 从token中获取id
            String token = authorization.replace("Bearer ", "");
            String username = tokenService.decode(token).getSubject();
            // 3. 进行绑定
            this.accountService.bindEmailWithUsername(bindEmailRequest.getEmail(), username);
            return Response.<String>builder()
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo())
                    .build();
        } catch (IllegalArgumentException exception) {
            log.error("UserAuthenticateController.bindEmail: {}", "参数异常");
            return Response.<String>builder()
                    .code(ResponseCode.ILLEGAL_PARAMETER.getCode())
                    .info(exception.getMessage() == null ? ResponseCode.ILLEGAL_PARAMETER.getCode() : exception.getMessage())
                    .build();
        } catch (AppException exception) {
            log.error("UserAuthenticateController.bindEmail - AppException: {}", exception.getInfo());
            return Response.<String>builder()
                    .code(exception.getCode())
                    .info(exception.getInfo())
                    .build();
        } catch (Exception exception) {
            log.error("UserAuthenticateController.bindEmail - Exception: {}", exception.getMessage());
            return Response.<String>builder()
                    .code(ResponseCode.SERVER_ERROR.getCode())
                    .info(ResponseCode.SERVER_ERROR.getInfo())
                    .build();
        } finally {
            log.info("UserAuthenticateController.bindEmail - end: {}", "设置密码结束");
        }
    }


    /**
     * todo 接口先不写，发不来手机验证码
     * 绑定手机号接口 - 短信验证 ROLE_ADMIN  ROLE_ADMIN
     */

    // @PreAuthorize("hasAnyRole('USER', 'ADMIN')")
    @RequestMapping(value = "test", method = RequestMethod.POST)
    public String test() {

        return "test";
    }

    @PreAuthorize("hasAnyRole('USER', 'ADMIN')")
    @RequestMapping(value = "test2", method = RequestMethod.POST)
    public String test2() {

        return "test";
    }

}